package hn.sigit.model.hnd.ladmshadow;

import hn.sigit.model.hnd.cadastre.HND_TaxStatusType;
import hn.sigit.model.hnd.ladmshadow.Property;
import hn.sigit.util.ParcelComparable;

import java.io.Serializable;
import java.math.BigDecimal;
import java.util.HashSet;
import java.util.Set;

import javax.persistence.*;

import org.hibernate.annotations.Type;

import com.vividsolutions.jts.geom.Point;
import com.vividsolutions.jts.geom.Polygon;


@Entity
@org.hibernate.annotations.Proxy(lazy=false)
@Table(name="Parcel", schema="ladmshadow")
@Inheritance(strategy=InheritanceType.JOINED)
@PrimaryKeyJoinColumn(name="SpatialUnitID", referencedColumnName="ID")
public class Parcel extends SpatialUnit implements Serializable, Cloneable, ParcelComparable {
	private static final long serialVersionUID = 1L;

	private Polygon shape;
	private Long fieldTab;
	private String cadastralKey;
	private String municipalKey;
	
	private BigDecimal geometryArea;
	private BigDecimal documentedArea;
	private BigDecimal measuredArea;
	private BigDecimal documentedBuiltArea;
	private BigDecimal groundBuiltArea;
	private String parcelName;
	private String neighborhood;
	private String accessWay1;
	private String accessWay2;
	private String houseNumber;
	private String locationInCountry;
	
	private BigDecimal commercialAppraisal;
	private BigDecimal fiscalAppraisal;
	private BigDecimal payedTaxes;
	private HND_TaxStatusType status;

	
	protected Parcel() {
	}
	
	public static Parcel newParcel(long ladmId, long presentationId, boolean isReadOnly, boolean isSnapshot) {
		Parcel parcel = new Parcel();
		
		parcel.setLadmId(ladmId);
		parcel.setPresentationId(presentationId);
		parcel.setReadOnly(isReadOnly);
		parcel.setSnapshot(isSnapshot);
		
		return parcel;
	}
	
	public static Parcel newDummyParcel() {
		return new Parcel();
	}
	
	@Column(name="Shape", nullable=false)
	@Type(type = "org.hibernatespatial.GeometryUserType")
	public Polygon getShape() {
		return shape;
	}
	public void setShape(Polygon value) {
		if (this.shape == null || !this.shape.equalsExact(value)) {
			this.shape = value;
			
			Point newRefPoint = value.getCentroid();
			newRefPoint.setSRID(value.getSRID());
			this.setReferencePoint(newRefPoint);
		}
	}
	
	@Column(name="FieldTab", nullable=true)
	public Long getFieldTab() {
		return fieldTab;
	}
	public void setFieldTab(Long fieldTab) {
		this.fieldTab = fieldTab;
	}
	
	@Column(name="CadastralKey", nullable=true)
	public String getCadastralKey() {
		return cadastralKey;
	}
	public void setCadastralKey(String cadastralKey) {
		this.cadastralKey = cadastralKey;
	}
	
	@Column(name="MunicipalKey", nullable=true)
	public String getMunicipalKey() {
		return municipalKey;
	}
	public void setMunicipalKey(String municipalKey) {
		this.municipalKey = municipalKey;
	}
	
	@Column(name="GeometryArea", nullable=true, precision=16, scale=8)
	public BigDecimal getGeometryArea() {
		return geometryArea;
	}
	public void setGeometryArea(BigDecimal geometryArea) {
		this.geometryArea = geometryArea;
	}
	
	@Column(name="DocumentedArea", nullable=true, precision=16, scale=8)
	public BigDecimal getDocumentedArea() {
		return documentedArea;
	}
	public void setDocumentedArea(BigDecimal documentedArea) {
		this.documentedArea = documentedArea;
	}
	
	@Column(name="MeasuredArea", nullable=true, precision=16, scale=8)
	public BigDecimal getMeasuredArea() {
		return measuredArea;
	}
	public void setMeasuredArea(BigDecimal measuredArea) {
		this.measuredArea = measuredArea;
	}
	
	@Column(name="DocumentedBuiltArea", nullable=true, precision=16, scale=8)
	public BigDecimal getDocumentedBuiltArea() {
		return documentedBuiltArea;
	}
	public void setDocumentedBuiltArea(BigDecimal documentedBuiltArea) {
		this.documentedBuiltArea = documentedBuiltArea;
	}
	
	@Column(name="GroundBuiltArea", nullable=true, precision=16, scale=8)
	public BigDecimal getGroundBuiltArea() {
		return groundBuiltArea;
	}
	public void setGroundBuiltArea(BigDecimal groundBuiltArea) {
		this.groundBuiltArea = groundBuiltArea;
	}
	
	@Column(name="ParcelName", nullable=true)
	public String getParcelName() {
		return parcelName;
	}
	public void setParcelName(String parcelName) {
		this.parcelName = parcelName;
	}
	
	@Column(name="Neighborhood", nullable=true)
	public String getNeighborhood() {
		return neighborhood;
	}
	public void setNeighborhood(String neighborhood) {
		this.neighborhood = neighborhood;
	}
	
	@Column(name="AccessWay1", nullable=true)
	public String getAccessWay1() {
		return accessWay1;
	}
	public void setAccessWay1(String accessWay1) {
		this.accessWay1 = accessWay1;
	}
	
	@Column(name="AccessWay2", nullable=true)
	public String getAccessWay2() {
		return accessWay2;
	}
	public void setAccessWay2(String accessWay2) {
		this.accessWay2 = accessWay2;
	}
	
	@Column(name="HouseNumber", nullable=true)
	public String getHouseNumber() {
		return houseNumber;
	}
	public void setHouseNumber(String houseNumber) {
		this.houseNumber = houseNumber;
	}
	
	@Column(name="LocationInCountry", nullable=true)
	public String getLocationInCountry() {
		return locationInCountry;
	}
	public void setLocationInCountry(String locationInCountry) {
		this.locationInCountry = locationInCountry;
	}
	
	@Column(name="CommercialAppraisal", nullable=true, precision=16, scale=8)
	public BigDecimal getCommercialAppraisal() {
		return commercialAppraisal;
	}
	public void setCommercialAppraisal(BigDecimal commercialAppraisal) {
		this.commercialAppraisal = commercialAppraisal;
	}
	
	@Column(name="FiscalAppraisal", nullable=true, precision=16, scale=8)
	public BigDecimal getFiscalAppraisal() {
		return fiscalAppraisal;
	}
	public void setFiscalAppraisal(BigDecimal fiscalAppraisal) {
		this.fiscalAppraisal = fiscalAppraisal;
	}
	
	@Column(name="PayedTaxes", nullable=true, precision=16, scale=8)
	public BigDecimal getPayedTaxes() {
		return payedTaxes;
	}
	public void setPayedTaxes(BigDecimal payedTaxes) {
		this.payedTaxes = payedTaxes;
	}
	
	@Column(name="Status", nullable=true)
	@Enumerated(EnumType.STRING)
	public HND_TaxStatusType getStatus() {
		return status;
	}
	public void setStatus(HND_TaxStatusType status) {
		this.status = status;
	}


	@Transient
	public Property getProperty() {
		Property prop = null;
		Set<BAUnit> baUnitSet = super.getBaunits();
		for (BAUnit baUnit : baUnitSet) {
			if (baUnit instanceof Property) {
				prop = (Property)baUnit;
				break;
			}
		}
		return prop;
	}
	
	
	@Override
	public Parcel clone() {
		try {
			Parcel clonedParcel = (Parcel) super.clone();
			
			//this is in order to mark the object as unsaved
			clonedParcel.setSuID(0);
			
			Set<BAUnit> baunits = new HashSet<BAUnit>(getBaunits());
			Set<SpatialUnit> element = new HashSet<SpatialUnit>(getElement());
			Set<SpatialUnitGroup> whole = new HashSet<SpatialUnitGroup>(getWhole());
			Set<SpatialSource> spatialSources = new HashSet<SpatialSource>(getSpatialSources());
			Set<RequiredRelationshipSpatialUnit> relSpatialUnits1requiredrelationshipspatialunits = new HashSet<RequiredRelationshipSpatialUnit>(getRelSpatialUnits1requiredrelationshipspatialunits());
			Set<RequiredRelationshipSpatialUnit> relSpatialUnits2requiredrelationshipspatialunits = new HashSet<RequiredRelationshipSpatialUnit>(getRelSpatialUnits2requiredrelationshipspatialunits());
			Set<BoundaryFaceString> bfsMinus = new HashSet<BoundaryFaceString>(getBfsMinus());
			Set<BoundaryFaceString> bfsPlus = new HashSet<BoundaryFaceString>(getBfsPlus());
			Set<BoundaryFace> bfMinus = new HashSet<BoundaryFace>(getBfMinus());
			Set<BoundaryFace> bfPlus = new HashSet<BoundaryFace>(getBfPlus());
			
			clonedParcel.setBaunits(baunits);
			clonedParcel.setElement(element);
			clonedParcel.setWhole(whole);
			clonedParcel.setSpatialSources(spatialSources);
			clonedParcel.setRelSpatialUnits1requiredrelationshipspatialunits(relSpatialUnits1requiredrelationshipspatialunits);
			clonedParcel.setRelSpatialUnits2requiredrelationshipspatialunits(relSpatialUnits2requiredrelationshipspatialunits);
			clonedParcel.setBfsMinus(bfsMinus);
			clonedParcel.setBfsPlus(bfsPlus);
			clonedParcel.setBfMinus(bfMinus);
			clonedParcel.setBfPlus(bfPlus);
			
			clonedParcel.setShape((Polygon)shape.clone());

			return clonedParcel;
		}
		catch (CloneNotSupportedException cnse) {
			cnse.printStackTrace();
		}
		return this;
	}

	public String toString() {
		return super.toString();
	}
	
}
